/**
 * 
 */
package org.dragonfire.util.token;

import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import org.dragonfire.file.BufferedFile;
import org.dragonfire.ti.TIFile;

/**
 * @author Darth Android
 * @date Oct 5, 2007
 */
public class TokenInputStream extends InputStream {

	public static void main(String[] args) {
		JFrame frame = new JFrame("Token Test");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(500, 500);
		JTextArea output = new JTextArea();
		// output.setFont(new Font("Courier New", Font.PLAIN, 12));
		GraphicsEnvironment.getLocalGraphicsEnvironment();
		output.setFont(new Font("Courier New", Font.PLAIN, 12));
		JScrollPane sp = new JScrollPane(output);
		frame.add(sp);
		frame.setVisible(true);
		TokenTable tt = TIFile.getTokenTable(TIFile.CALC_8X);
		TIFile tif = new TIFile(BufferedFile.openFile("<prgms/_theta_INPUT.8xp>"));
		InputStream is = tif.getVars().get(0).dataAsInputStream();
		try {
			is.read();
			is.read();
		} catch (Exception e) {
		}
		Scanner in = new Scanner(new TokenInputStream(tt, is, false, "UTF-8"), "UTF-8");
		if (in.hasNextLine()) {
			output.setText(in.nextLine());
			while (in.hasNextLine()) {
				output.setText(output.getText() + "\n" + in.nextLine());
			}
		}
	}

	private TokenTable table;
	private InputStream stream;
	// private StringBuffer buffer = new StringBuffer();
	private ByteBuffer bbuffer = null;
	private boolean edit = true;
	private Charset charset;
	private CharsetEncoder encoder;

	/**
	 * 
	 */
	public TokenInputStream(TokenTable table, InputStream inStream, boolean editText, String charSet) {
		if (inStream == null)
			throw new NullPointerException("inStream may not be null");
		if (!inStream.markSupported())
			throw new IllegalArgumentException("inStream must support mark(int)");
		this.table = table;
		stream = inStream;
		edit = editText;
		charset = Charset.forName(charSet);
		encoder = charset.newEncoder();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int read() throws IOException {
		if (bbuffer == null || bbuffer.hasRemaining() == false) {
			int first = stream.read();
			if (first == -1)
				return -1;
			ArrayList<Byte> rawTokens = new ArrayList<Byte>();
			rawTokens.add((byte) first);
			while (stream.available() > 0)
				rawTokens.add((byte) stream.read());
			Token[] toks = table.readTokens(rawTokens.toArray(new Byte[rawTokens.size()]));
			String text = "";
			for (Token t : toks) {
				text += edit ? t.getEditText() : t.getDisplayText();
			}
			// buffer.append(edit ? t.getEditText() : t.getDisplayText());
			bbuffer = encoder.encode(CharBuffer.wrap(text));
		}
		int c = bbuffer.get();
		/*
		 * int c = (int) buffer.charAt(0); buffer.deleteCharAt(0);
		 */
		return c;
	}
}
